package com.jsh.erp.service.report;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jsh.erp.constants.BusinessConstants;
import com.jsh.erp.datasource.entities.*;
import com.jsh.erp.datasource.mappers.DepotItemMapperEx;
import com.jsh.erp.datasource.mappers.MaterialExtendMapper;
import com.jsh.erp.datasource.mappers.MaterialMapper;
import com.jsh.erp.datasource.mappers.ReportMaterialInventoryDailyMapper;
import com.jsh.erp.service.depot.DepotService;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

@Service
public class ReportMaterialInventoryDailyService {
    @Autowired private ReportMaterialInventoryDailyMapper reportMaterialInventoryDailyMapper;
    @Autowired private MaterialExtendMapper materialExtendMapper;
    @Autowired private DepotItemMapperEx depotItemMapperEx;
    @Autowired private MaterialMapper materialMapper;
    @Autowired private DepotService depotService;


    public Map<String, JSONArray> handleByDepot(){
        Map<String, JSONArray> depotMaterialMap = Maps.newHashMap();
        try {
            List<Depot> depotList = depotService.getDepot();
            for (int i = 0; i < depotList.size(); i++) {
                depotMaterialMap.put(depotList.get(i).getId().toString(), new JSONArray());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        MaterialExample example = new MaterialExample();
        example.createCriteria().andDeleteFlagEqualTo(BusinessConstants.DELETE_FLAG_EXISTS);
        List<Material> materials = materialMapper.selectByExample(example);
        JSONArray results = new JSONArray();
        for (Material material : materials){
            JSONObject result = getMaterialDetails(material.getId());
            JSONArray depotPriceCounts = result.getJSONArray("priceCounts");
            for (int i = 0; i < depotPriceCounts.size(); i++) {
                JSONObject depotPriceCountItem = depotPriceCounts.getJSONObject(i);
                String depotId = depotPriceCountItem.getString("depotId");
                JSONObject priceCount = depotPriceCountItem.getJSONObject("priceCount");
                if ( priceCount.isEmpty()){
                    continue;
                }
                depotMaterialMap.get(depotId).add(new JSONObject().fluentPut("materialId",material.getId()).fluentPut("priceCount",priceCount));
            }
        }
        return depotMaterialMap;
    }


    /**
     *
     select
     depot_head.create_time,
     depot_item.depot_id,
     depot_head.type,
     depot_head.sub_type,
     depot_item.oper_number,
     depot_item.material_unit,
     depot_item.purchase_decimal,
     depot_item.purchase_unit_price,
     depot_item.tax_last_money,
     depot_item.tax_money,
     depot_item.tax_rate,
     depot_item.tax_unit_price,
     depot_head.number,
     depot_head.link_number,
     depot_item.id,
     depot_item.material_id,
     depot_item.header_id
     from jsh_depot_item as depot_item
     left join jsh_depot_head as depot_head on depot_item.header_id = depot_head.id
     where depot_item.material_id = 4928 and depot_head.status = '1'
     order by depot_head.create_time
     * @param materialId
     */
    public JSONObject getMaterialDetails(Long materialId){
        List<String> logs = Lists.newArrayList();
        MaterialExtendExample example = new MaterialExtendExample();
        example.createCriteria().andMaterialIdEqualTo(materialId).andDeleteFlagNotEqualTo(BusinessConstants.DELETE_FLAG_DELETED);
        List<MaterialExtend> materialExtends = materialExtendMapper.selectByExample(example);

        Map<String, Queue<BigDecimal>> depotMaterialPriceQueueMap = Maps.newHashMap();
        List<Map<String, Object>> depotDetailList = depotItemMapperEx.selectDepotDetailByMaterialId(materialId);
        for (Map<String,Object> depotDetail : depotDetailList){
            String createTime = depotDetail.get("create_time").toString();
            String depot = depotDetail.get("depot_id") == null ? null : depotDetail.get("depot_id").toString();
            String depotType = depotDetail.get("type").toString();
            String depotSubType = depotDetail.get("sub_type").toString();
            String linkNumber = depotDetail.get("link_number") == null ? null : depotDetail.get("link_number").toString();
            if ( depot == null ){
                logs.add(createTime+", 单据["+depotType+"]["+depotSubType+"]["+depotDetail.get("number")+"],数量:"+depotDetail.get("oper_number"));
                continue;
            }

            if ( depotMaterialPriceQueueMap.get(depot) == null  ){
                depotMaterialPriceQueueMap.put(depot, new LinkedBlockingQueue<>());
            }

            // 入库逻辑
            if ( depotType.equals("入库") ){
                //采购入库,根据采购入库单中找到采购订单
                if ( depotSubType.equals("采购") || depotSubType.equals("其它") ){
                    //使用默认单价
                    BigDecimal purchasePrice = materialExtends.get(0).getPurchaseDecimal();
//                    logs.add(createTime+", 入库,单据["+depotType+"]["+depotSubType+"]["+depotDetail.get("number")+"],数量:"+depotDetail.get("oper_number")+",默认单价:"+purchasePrice);
                    if ( linkNumber != null ){
                        //如果关联订单不为空， 则使用入库单价
                        purchasePrice = getPurchasePrice(linkNumber,depotDetailList);
                        if ( purchasePrice != null ) {
                            logs.add(createTime + ", 入库,单据[" + depotType + "][" + depotSubType + "][" + depotDetail.get("number") + "],数量:" + depotDetail.get("oper_number") + ",关联订单不为空，使用单据[" + linkNumber + "]中的单价:" + purchasePrice);
                        }else{
                            purchasePrice = materialExtends.get(0).getPurchaseDecimal();
                        }
                    }

                    if ( purchasePrice == null ){
                        purchasePrice = new BigDecimal(0);
                        logs.add(createTime+", 入库,单据["+depotType+"]["+depotSubType+"]["+depotDetail.get("number")+"],数量:"+depotDetail.get("oper_number")+",无默认单价且无关联采购订单，使用默认单价:"+purchasePrice.toString());
                    }

                    int count = new BigDecimal(depotDetail.get("oper_number").toString()).intValue();
                    for (int i=0 ;i<count; i++ ){
                        depotMaterialPriceQueueMap.get(depot).offer(purchasePrice);
                    }
                    logs.add(createTime+", 入库,单据["+depotType+"]["+depotSubType+"]["+depotDetail.get("number")+"],入库数量:"+depotDetail.get("oper_number")+",单价:"+purchasePrice.toString()+",库存数量:"+depotMaterialPriceQueueMap.get(depot).size());

                }  else if (depotSubType.equals("销售退货")) {
                    //purchase_unit_price有值
                    int count = new BigDecimal(depotDetail.get("oper_number").toString()).intValue();
                    for (int i=0 ;i<count; i++ ){
                        BigDecimal purchasePrice = depotDetail.get("purchase_unit_price") == null ?  materialExtends.get(0).getPurchaseDecimal() : new BigDecimal(0);
                        purchasePrice = purchasePrice != null ? purchasePrice : new BigDecimal(0);
                        depotMaterialPriceQueueMap.get(depot).offer(purchasePrice);
                    }
                    logs.add(createTime+", 入库,单据["+depotType+"]["+depotSubType+"]["+depotDetail.get("number")+"],数量:"+depotDetail.get("oper_number")+",单价:"+depotDetail.get("purchase_unit_price"));
                }else{

                }
            }

            //出库逻辑
            if ( depotType.equals("出库") ){
                if ( depotSubType.equals("销售") ){

                    int count = new BigDecimal(depotDetail.get("oper_number").toString()).intValue();
                    Map<String,Integer> purchaseDecimalMaps = Maps.newHashMap();
                    for (int i=0 ;i<count; i++ ){
                        BigDecimal purchaseDecimal = depotMaterialPriceQueueMap.get(depot).poll();
                        if ( purchaseDecimal == null ){
                            purchaseDecimal = materialExtends.get(0).getPurchaseDecimal() != null ? materialExtends.get(0).getPurchaseDecimal() : new BigDecimal(0);
                            if ( purchaseDecimalMaps.get(purchaseDecimal.toString()) == null ){
                                purchaseDecimalMaps.put(purchaseDecimal.toString(),0);
                            }
                            purchaseDecimalMaps.put(purchaseDecimal.toString(),purchaseDecimalMaps.get(purchaseDecimal.toString())+1);
                            logs.add(createTime+", 出库,单据["+depotType+"]["+depotSubType+"]["+depotDetail.get("number")+"],数量:"+depotDetail.get("oper_number")+", 单价:"+purchaseDecimal.toString()+",出库数量不足:"+(i+1)+"/"+count);
                            continue;
                        }
                        if ( purchaseDecimalMaps.get(purchaseDecimal.toString()) == null ){
                            purchaseDecimalMaps.put(purchaseDecimal.toString(),0);
                        }
                        purchaseDecimalMaps.put(purchaseDecimal.toString(),purchaseDecimalMaps.get(purchaseDecimal.toString())+1);
                    }

                    logs.add(createTime+", 出库,单据["+depotType+"]["+depotSubType+"]["+depotDetail.get("number")+"],出库数量:"+depotDetail.get("oper_number")+",库存数量:"+depotMaterialPriceQueueMap.get(depot).size()+",出库价格列表:"+JSONObject.toJSONString(purchaseDecimalMaps));
                }
            }
        }

        JSONArray depotCountPrice = new JSONArray();
        for (String depotId : depotMaterialPriceQueueMap.keySet()){
            Queue<BigDecimal> priceQueue = depotMaterialPriceQueueMap.get(depotId);

            Map<String,Integer> priceCount = Maps.newHashMap();
            priceQueue.forEach(price -> {
                String priceStr = price.toString();
                if ( priceCount.get(priceStr) == null ){
                    priceCount.put(priceStr,0);
                }
                priceCount.put(priceStr, priceCount.get(priceStr)+1);
            });

            depotCountPrice.add(new JSONObject().fluentPut("depotId",depotId).fluentPut("priceCount",priceCount));
        }

        return new JSONObject().fluentPut("priceCounts",depotCountPrice).fluentPut("logs", JSONArray.toJSON(logs));
    }

    //根据采购入库单中link_number找到本次入库的材料单价
    public BigDecimal getPurchasePrice(String cgddNumber, List<Map<String, Object>> depotDetailList){
        for (Map<String,Object> depotDetail : depotDetailList){
            if ( cgddNumber.equals(depotDetail.get("number").toString()) ){
                return depotDetail.get("purchase_decimal") != null ? new BigDecimal(depotDetail.get("purchase_decimal").toString()) : new BigDecimal(0);
            }
        }
        return null ;
    }
}
